/*
 * anima/space.hh - Generic address space interface.
 * Copyright (C) 2007  Mikhail Vorozhtsov
 * See the LICENSE section of the README file for details.
 */

/* $Id$ */

#ifndef HEADER_ANIMA_SPACE_HH
#define HEADER_ANIMA_SPACE_HH

#include ANIMA_ARCH_HEADER (space.hh)
#include HEADER (anima,pdb.hh)
#include HEADER (anima,mm.hh)
#include HEADER (anima,object.hh)

START_NAMESPACE (anima)

struct space_t : object_t, ANIMA_ARCH::space_t
{
private:
  struct mapping_t;

  struct share_t
  {
    pdb::lvl1e_t *page;
    mapping_t *first_mapping;
    space_ref_t prev_space;
    space_ref_t next_space;

    INLINE
    bool
    operator< (const share_t &share)
    {
      return page < share.page;
    }
  };

  struct mapping_t
  {
    mm::tte_t *tte;
    share_t *share;
    mapping_t *prev;
    mapping_t *next;
  };

private:
  pdb::lvl1e_t *free_lvl1e;
  pdb::lvl1e_t *used_lvl1e;
  pdb::lvl1e_t *reserved_lvl1e;
  pdb::lvl1e_t *specials_lvl1e;
  pdb::lvl1e_t *shared_lvl1e;

private:
  thread_t *threads;

public:
  static space_t *create ();

private:
  bool init_instance ();

public:
  void add (thread_t *thread);

public:
  void accept (pdb::lvl1e_t *lvl1e);
  void adopt (pdb::lvl1e_t *lvl1e);
  pdb::lvl1e_t *allocate (pdb::entry_t::usage_t usage);
  void deallocate (pdb::lvl1e_t *lvl1e);

public:
  void *map (u64_t addr, mm::tte_t::flag_t flags = mm::tte_t::FLAG_DEFAULTS);
  void *map (u64_t paddr, u64_t addr,
             mm::tte_t::flag_t flags = mm::tte_t::FLAG_DEFAULTS);
  bool map_range (u64_t start, u64_t end,
                  mm::tte_t::flag_t flags = mm::tte_t::FLAG_DEFAULTS);
  bool map_range (u64_t paddr, u64_t start, u64_t end,
                  mm::tte_t::flag_t flags = mm::tte_t::FLAG_DEFAULTS);
  void unmap (u64_t addr);
};

END_NAMESPACE

#endif /* HEADER_ANIMA_SPACE_HH */

